<template>
  <div class="stepper">
    <el-dialog
        v-model="stepperDialogVisible"
        @closed="closed"
        destroy-on-close
        width="30%"
    >
      <template #header>
        <span>
          {{props.stepperTitle}}
        </span>
      </template>
      <div class="container">
        <template v-for="(comp,index) in registerComponents">
          <component
              ref="stepperComp"
              v-show="activeStepperIndex === index"
              :is="comp"
              :ctxFormData="ctxFormData"
              @changeCtxFormData="changeCtxFormData"
          ></component>
        </template>
      </div>
      <template #footer>
        <el-button style="margin-top: 12px;" @click="previousStep" :disabled="activeStepperIndex === 0">上一步</el-button>
        <el-button style="margin-top: 12px;" @click="finishedStep" v-if="activeStepperIndex === registerComponents.length - 1">完成</el-button>
        <el-button style="margin-top: 12px;" type="primary" @click="nextStep" :disabled="activeStepperIndex === registerComponents.length - 1" v-else>下一步</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import {computed, nextTick, onMounted, ref, watch} from "vue";
import store from '@/store/index'

const emit = defineEmits(['finished-step','closed'])
const props = defineProps({
  registerComponents: {
    type: [Array],
    default: []
  },
  stepperTitle: {
    type: [String],
    default: ''
  }
})
let stepperDialogVisible = ref(false)
let stepperComp = ref(null)
let activeStepperIndex = ref(0)
let editId = ref(null)
// 重置 stepper
const resetStepper = () => {
  activeStepperIndex.value = 0
  store.commit("CLEAR_CTX_FORM_DATA");
}
// 上一步
const previousStep = () => {
  activeStepperIndex.value--
  if (stepperComp.value[activeStepperIndex.value]?.show) stepperComp.value[activeStepperIndex.value]?.show()
}
// 下一步
const nextStep = () => {
  // 切换之前 需校验当前page  page: validateCurrent: 校验当前页的方法
  let lastPage = stepperComp.value[activeStepperIndex.value]
  if (lastPage.validateCurrent) {
    lastPage.validateCurrent().then(res=>{
      activeStepperIndex.value++
      if (stepperComp.value[activeStepperIndex.value]?.show) stepperComp.value[activeStepperIndex.value]?.show()
    })
    return
  }
  activeStepperIndex.value++
  if (stepperComp.value[activeStepperIndex.value]?.show) stepperComp.value[activeStepperIndex.value]?.show()
}
// 完成
const finishedStep = () => {
  checkAllForm().then(res=>{
    emit('finished-step', ctxFormData,editId.value)
  })
}
// 校验所有表单
const checkAllForm = () => {
  return new Promise(resolve => {
    let result = stepperComp.value.filter(comp => {
      return comp.validateCurrent
    })
    let r1 = result.map(item=>{
      return item['validateCurrent']()
    })
    Promise.all(r1).then(res=>{
      resolve()
    })
  })
}
// ctxFormData
const ctxFormData = computed(()=> store.state.ctxFormData)
// Dialog 关闭动画结束时的回调
const closed = () => {
  resetStepper()
  emit('closed')
}

// 一： stepper 入口
// 1.isShow：打开/关闭；
// 2.form：同步给所有表单的数据；编辑时将数据赋值给各个表单
// 3.id：编辑id
const onShow = (isShow,form,id) => {
  stepperDialogVisible.value = isShow
  editId.value = id
  nextTick(()=>{
    if (isShow) {
      syncCtxFormData(form)
    } else {
      // 重置 stepper
      resetStepper()
    }
  })
}

//更改大表单中的项
const changeCtxFormData = (key, value) => {
  store.commit("CHANGE_CTX_FORM_DATA", {key, value});
  let changForm = {}
  changForm[key] = value
  syncCtxFormData(changForm)
}

// 二 form -> ctxFormData  (监视子组件的form,同步到 ctxFormData)
// 新建和编辑都能将form 同步到各个表单
const syncCtxFormData = (form) => {
  if (!stepperComp.value) return
  stepperComp.value.forEach(comp => {
    // 将 所有数据 同步到各个小form
    _.assign(comp.form,form)
    // 监视各个小form，小form改变同步到 ctxFormData
    watch(()=> comp.form,(v)=>{
      store.commit("SYNC_CTX_FORM_DATA", v);
    },{immediate: true,deep: true})
  })
}

onMounted(()=>{
})

watch(()=>props.registerComponents,(v)=>{
},{immediate: true,deep: true})

defineExpose({
  onShow
})
</script>

<style scoped lang="less">
.stepper {
  width: 1200px;
  .container {
    display: flex;
    justify-content: center;
    margin: 16px;
  }
  :deep(.el-dialog__header) {
    border-bottom: 1px solid #dbdcdc;
  }
  :deep(.el-dialog__footer) {
    border-top: 1px solid #dbdcdc;
  }
}
</style>

<!--

stepper
1.入口：onShow
2.数据同步：syncCtxFormData
3.更改ctxFormData: changeCtxFormData

1.ctxFormData: 全表单数据

子组件中可定义:
1. form                  //表单
2. show                  //组件切换时触发
3. validateCurrent       //校验当前激活组件

-->